package com.dianping.cat.local.integration.servlet;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dianping.cat.Cat;
import com.dianping.cat.servlet.CatFilter;
import com.dianping.cat.util.Files;
import com.dianping.cat.util.StringUtils;

// ======================================================= INNER CLASS

/**
 * <p>
 * 对官方提供的Filter进行增强, 通过微服务方式调用过来的HTTP请求将不作记录
 * 
 * @see HttpCatCrossFliter
 * @author LQ
 *
 */
public class CatFilterDecorator extends CatFilter {

	private static final Logger logger = LoggerFactory.getLogger(CatFilterDecorator.class);

	/**
	 * <p>
	 * 启用CAT的链路跟踪模式, 也就是CAT将向URL请求返回值的HEADER部分插入一个名为 X-ROOT-TRACE-ID 的KEY-VALUE.
	 * 默认启用
	 */
	private boolean enableTraceMode;

	/**
	 * 诸如cat.html的内部静态资源的读取, 是否自己处理, 默认为false
	 */
	private boolean staticResourceDealedSelf;

	public CatFilterDecorator(final boolean enableTraceMode) {
		this.enableTraceMode = enableTraceMode;
	}

	public CatFilterDecorator() {
		this(true);
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
			throws IOException, ServletException {
		final HttpServletRequest request = (HttpServletRequest) req;
		final String requestURI = request.getRequestURI();
		if (StringUtils.isNotEmpty(request.getHeader(Cat.Context.ROOT))) {
			logger.debug("【CatFilter】 {},为CAT远程调用(Remote Invoke), 直接放行", requestURI);
			filterChain.doFilter(req, resp);
			return;
		}

		if (enableTraceMode) {
			Cat.getManager().setTraceMode(true);
		}

		if (isVisitInnerCatStaticResource(requestURI) && staticResourceDealedSelf) {
			Files.forIO().copy(Thread.currentThread().getContextClassLoader()
					.getResourceAsStream("META-INF/resources" + requestURI), resp.getOutputStream());
		} else {
			super.doFilter(request, resp, filterChain);
		}

	}

	protected boolean isVisitInnerCatStaticResource(final String requestURI) {
		return requestURI.startsWith("/cat/")
				&& (requestURI.endsWith(".html") || requestURI.endsWith(".js") || requestURI.endsWith(".css"));
	}

	@Override
	public void init(FilterConfig filterConfig) {
		super.init(filterConfig);

		if (StringUtils.isNotEmpty(filterConfig.getInitParameter("trace-mode"))) {
			enableTraceMode = Boolean.parseBoolean(filterConfig.getInitParameter("trace-mode"));
		}

		staticResourceDealedSelf = Boolean.parseBoolean(filterConfig.getInitParameter("deal-inner-static-resource"));
	}

}